package com.sp.system.user.core.utils.security;


import com.google.gson.Gson;
import com.sp.system.user.core.entity.SecurityUserDetails;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

/**
 * @Describle 生成token 方法
 * @author chenanhai
 * @Date 2019年9月3日
 */
@Slf4j
@Component
public class JwtTokenUtil {

    /**
     * JWT签名加密key
     */
    public static String secret;
    /**
     * token分割
     */
    public static String tokenPrefix;
    /**
     * token参数头
     */
    public static String tokenHeader;
    /**
     * 权限参数头
     */
    public static String authHeader;
    /**
     * token有效期
     */
    public static Integer tokenExpireTime;
    /**
     * token 刷新时间
     */
    public static Integer refreshTokenExpiration;

    /**
     * 不需要认证的接口
     */
    public static String antMatchers;


    public static String generateAccessToken(UserDetails userDetails){
        SecurityUserDetails securityUserDetails = (SecurityUserDetails) userDetails;
        String token = Jwts.builder()
                .setSubject(securityUserDetails.getLoginName()) //主题 放入用户名
                .setId(securityUserDetails.getId())
                //iat: jwt的签发时间
                .setIssuedAt(new Date())
                //自定义属性 放入用户拥有权限
                .claim(authHeader, new Gson().toJson(securityUserDetails.getAuthorities()))
                //失效时间
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000))
                //签名算法和密钥
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
        log.info("token 创建信息--》{{}}{{}}",new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000),token);
        return token;
    }
    /**
     * 重置(更新)token 过期时间
     * @param token
     */
    public static String resfreshToken(String token){
        String refreshedToken;
        try {
            Claims claims = getClaimsFromToken(token);
            claims.put("created", new Date());
            refreshedToken = generateToken(claims);
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }
    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    private static String generateToken(Map<String, Object> claims) {
        //有效时间
        Date expirationDate = new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000);
        return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS256, secret).compact();
    }
    /***
     * 解析token 信息
     * @param token
     * @return
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(JwtTokenUtil.secret)
                    .parseClaimsJws(token.replace(JwtTokenUtil.tokenPrefix, ""))
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }


    /**
     * 判断令牌是否过期
     *
     * @param token 令牌
     * @return 是否过期
     */
    public static Boolean isTokenExpired(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            return false;
        }
    }


    @Value("${jwt.secret}")
    public void setSecret(String secret) {
        JwtTokenUtil.secret = secret;
    }
    @Value("${jwt.tokenPrefix}")
    public void setTokenPrefix(String tokenPrefix) {
        JwtTokenUtil.tokenPrefix = tokenPrefix;
    }
    @Value("${jwt.tokenHeader}")
    public void setTokenHeader(String tokenHeader) {
        JwtTokenUtil.tokenHeader = tokenHeader;
    }
    @Value("${jwt.authHeader}")
    public void setAuthHeader(String authHeader) {
        JwtTokenUtil.authHeader = authHeader;
    }
    @Value("${jwt.expiration}")
    public void setTokenExpireTime(Integer tokenExpireTime) {
        JwtTokenUtil.tokenExpireTime = tokenExpireTime;
    }
    @Value("${jwt.refreshToken}")
    public void setRefreshTokenExpiration(Integer refreshTokenExpiration) {
        JwtTokenUtil.refreshTokenExpiration = refreshTokenExpiration;
    }
    @Value("${jwt.antMatchers}")
    public void setAntMatchers(String antMatchers) {
        JwtTokenUtil.antMatchers = antMatchers;
    }
}
